# -*- coding: utf-8 -*-
# Copyright 2011-2012 MagiCycles.com
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


import logging
from urlparse import urljoin

from google.appengine.api import users

from django.http import HttpResponseRedirect
from lib.gaesessions import get_current_session
from lib.weibo import get_weibo_client

from datastore.common import OutSites,OutSitesTypes,UserError
from datastore.people import OutSiteUser,SiteUser


class ImageMime:
    GIF = "image/gif"
    JPEG = "image/jpeg"
    TIFF = "image/tiff"
    PNG = "image/png"
    BMP = "image/bmp"
    ICO = "image/x-icon"
    UNKNOWN = "application/octet-stream"

    WEIBO_SUPPORTED_IMAGES = [GIF, JPEG, PNG]

def get_img_type(binary):
    size = len(binary)
    if size >= 6 and binary.startswith("GIF"):
        return ImageMime.GIF
    elif size >= 8 and binary.startswith("\x89PNG\x0D\x0A\x1A\x0A"):
        return ImageMime.PNG
    elif size >= 2 and binary.startswith("\xff\xD8"):
        return ImageMime.JPEG
    elif (size >= 8 and (binary.startswith("II\x2a\x00") or
                         binary.startswith("MM\x00\x2a"))):
        return ImageMime.TIFF
    elif size >= 2 and binary.startswith("BM"):
        return ImageMime.BMP
    elif size >= 4 and binary.startswith("\x00\x00\x01\x00"):
        return ImageMime.ICO
    else:
        return ImageMime.UNKNOWN
    
class OutSiteHelpler(object):

    def __init__(self, site=None):
        self._site = site

    @classmethod
    def logout(cls):
        session = get_current_session()
        session.clear()

    def create_auth_url(self, callback):
        method_name = "_create_auth_url_%s"%self._site
        method = self.__getattribute__(method_name)
        return method(callback)

    def _create_auth_url_Google(self, goog_callback):
        return users.create_login_url(goog_callback)

    def _create_auth_url_Weibo(self, weibo_callback):
        weibo_client = get_weibo_client()
        auth_url = weibo_client.get_authorization_url_with_callback(weibo_callback)
        return auth_url

    def bind_outsite(self, request, user, save_senssion=False):
        method_name = "_bind_outsite_%s"%self._site
        method = self.__getattribute__(method_name)
        return method(request, user, save_senssion)

    def _bind_outsite_Google(self, request, user, save_senssion=False):
        outsite_user = self._check_outsite_user_Google(request, save_senssion)
        if not outsite_user:
            return False
        try:
            SiteUser.bind_outsite_user(user, outsite_user)
            save_senssion and self._update_user_info_Google(user, outsite_user)
        except Exception,e:
            logging.exception("_bind_outsite_Google: %s"%e)
            raise e
        return True

    def _bind_outsite_Weibo(self, request, user, save_senssion=False):
        outsite_user = self._check_outsite_user_Weibo(request, save_senssion)
        if not outsite_user:
            return False
        try:
            SiteUser.bind_outsite_user(user, outsite_user)
            save_senssion and self._update_user_info_Weibo(user, outsite_user)
        except Exception,e:
            logging.exception("_bind_outsite_Weibo: %s"%e)
            raise e
        return True

    def update_user_info(self, user, outsite_user, request=None):
        method_name = "_update_user_info_%s"%self._site
        method = self.__getattribute__(method_name)
        return method(user, outsite_user, request)

    def _update_user_info_Google(self, user, outsite_user, request=None):
        save_outsite_user(outsite_user)
        
    def _update_user_info_Weibo(self, user, outsite_user, request=None):
        save_outsite_user(outsite_user)

    def check_outsite_user(self, request):
        method_name = "_check_outsite_user_%s"%self._site
        method = self.__getattribute__(method_name)
        return method(request)

    def _check_outsite_user_Google(self, request, save_senssion=True):
        googleuser = users.get_current_user()
        if not googleuser:
            return False
        uid = "%s@google"%googleuser.email()
        name = googleuser.nickname()
        outsite_user = OutSiteUser.get_or_create(uid, name=name, site=OutSites.Google, email = googleuser.email(),
                                                 is_tweetable=False, enable_twitter=False,
                                                 access_token_key="", access_token_secret ="")
        if save_senssion:
            save_outsite_user(outsite_user)
        return outsite_user

    def _check_outsite_user_Weibo(self, request, save_senssion=True):
        try:
            code = request.GET.get('code', None)

            weibo_client = get_weibo_client()

            r = weibo_client.request_access_token(code)
            access_token, expires_in, weibo_id = r.access_token, str(r.expires_in), r.uid

            if not access_token:
                raise Exception("can not get access token")

            weibo_client.set_access_token(access_token, expires_in)

            uid = "%s@weibo.com"%weibo_id
            try:
                weibouser = weibo_client.users.show.get(uid=weibo_id)
                name = weibouser.screen_name
                photourl = weibouser.profile_image_url
            except:
                name = uid
                photourl = ""

            outsite_user = OutSiteUser.get_or_create(uid, name=name, site=OutSites.Weibo, email = uid,
                                                     is_tweetable=False, enable_twitter=False, photourl=photourl,
                                                     access_token_key=access_token,
                                                     access_token_secret=access_token,
                                                     expired_time=expires_in)
            outsite_user.photourl = photourl
            outsite_user.access_token_key = access_token
            outsite_user.access_token_secret = access_token
            outsite_user.expired_time = expires_in
            outsite_user.save()
            if save_senssion:
                save_outsite_user(outsite_user)
            return outsite_user
        except:
            logging.exception("check_weibo_user error")
            return False


    def post_activity(self, outsiteuser, msg, photourl=None, annotations="", lat="", long=""):
        method_name = "_post_activity_%s"%(self._site or outsiteuser.site)
        method = self.__getattribute__(method_name)
        return method(outsiteuser, msg, photourl, annotations, lat, long)

    def _post_activity_Google(self, outsiteuser, msg, photourl=None, annotations="", lat="", long=""):
        pass

    def _post_activity_Weibo(self, outsiteuser, msg, photourl=None, annotations="", lat="", long=""):
        weibo_client = get_weibo_client()
        weibo_client.set_access_token(outsiteuser.access_token_key, outsiteuser.expired_time)
        try:
            photo_binary = None
            if photourl:
                from google.appengine.api import urlfetch
                result = urlfetch.fetch(photourl, deadline=15)
                if result.status_code == 200:  # photo binary success, post image
                    photo_binary = result.content
                    file_type = get_img_type(photo_binary)
                    if file_type not in ImageMime.WEIBO_SUPPORTED_IMAGES:
                        photo_binary = None

            if photo_binary is not None:
                weibo_client.statuses.upload.post(status=msg, pic=photo_binary,
                    lat=lat, long=long, annotations=annotations)
            else:
                weibo_client.statuses.update.post(status=msg, lat=lat, long=long, annotations=annotations)

            logging.info("Success _post_activity_Weibo for %s"%outsiteuser.uid)
        except:
            logging.exception("Error in _post_activity_Weibo")

    def _get_short_url(self, long_url):
        if len(long_url) <= 50:
            return long_url
        import simplejson
        from google.appengine.api import urlfetch
        postdict = {
          "key": 'AIzaSyDta9_Ki8Eb0zhfNcQ7U5hBqzT8t8aNTFw',
          "longUrl": long_url,
        }
        goog_host = "https://www.googleapis.com/urlshortener/v1/url"

        postdata = simplejson.dumps(postdict)
        result = urlfetch.fetch(url=goog_host,
                                payload=postdata,
                                method=urlfetch.POST,
                                headers={'Content-Type': 'application/json'},
                                deadline=20)
        if result.status_code == 200:
            res = simplejson.loads(result.content)
            if res.get("id"):
                return res.get("id")
            else:
                return ""
        return ""

def get_outsite_user():
    session = get_current_session()
    uid = session.get("outsite_user_id", None)
    return uid and OutSiteUser.get_by_uid(uid)

def save_outsite_user(outsite_user):
    session = get_current_session()
    session["outsite_user_id"] = outsite_user.uid
    return outsite_user

def refresh_outsite_user():
    outsite_user = get_outsite_user()
    if outsite_user:
        outsite_user = OutSiteUser.get_by_uid(outsite_user.uid)
        save_outsite_user(outsite_user)

def create_login_urls(common_login_url):
    urls = {}
    for site in OutSitesTypes:
        urls[site] = urljoin(common_login_url, site)
    return urls

def logout(request):
    outsite_user = get_outsite_user()

    OutSiteHelpler.logout()

    if outsite_user and outsite_user.site == OutSites.Google:
        return HttpResponseRedirect(users.create_logout_url(request.META.get('HTTP_REFERER','/')))

    return HttpResponseRedirect(request.META.get('HTTP_REFERER','/'))

def create_auth_url(site, outsite_callback):
    outsite_helper = OutSiteHelpler(site)
    return outsite_helper.create_auth_url(outsite_callback)

def check_outsite_user(request, site):
    outsite_helper = OutSiteHelpler(site)
    return outsite_helper.check_outsite_user(request)

def update_user_info(user, outsiteuser, request=None):
    outsite_helper = OutSiteHelpler(outsiteuser.site)
    outsite_helper.update_user_info(user, outsiteuser)
    pass

def bind_outsite(request, user, outsite, save_senssion=False):
    """ Bind another outsite user, need current user login
    """
    outsite_helper = OutSiteHelpler(outsite)
    return outsite_helper.bind_outsite(request, user, save_senssion)

def post_activity(outsiteuser, msg, photourl=None, annotations="", lat="", long=""):
    outsite_helper = OutSiteHelpler(outsiteuser.site)
    outsite_helper.post_activity(outsiteuser, msg, photourl, annotations, lat, long)
    
